/**
 * 
 */
package com.feizhi.common.upload;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.context.request.NativeWebRequest;

import com.feizhi.common.upload.bean.UploadedFile;

/**
 * @author shuaqiu 2013年11月29日
 * 
 */
public class UploadFileUtil {
	/**
	 * 
	 */
	private static final String UPLOAD_BASE = "upload";

	private static final Log log = LogFactory.getLog(UploadFileUtil.class);

	private static String realPath;

	/**
	 * 在baseFolder 目录下创建子文件夹. 返回的子文件夹是这样的: <br/>
	 * baseFolder / folderNames[0] / folderNames[1] / folderNames[2] / ...
	 * 
	 * @param baseFolder
	 *            根目录
	 * @param folderNames
	 *            子文件夹名称
	 * @return
	 */
	public static synchronized File getFolder(File baseFolder, String... folderNames) {
		File folder = baseFolder;
		for (String name : folderNames) {
			folder = new File(folder, name);
		}

		if (!folder.exists()) {
			folder.mkdirs();
		}

		return folder;
	}

	/**
	 * @param req
	 * @return
	 */
    public static synchronized File getBaseFolder(NativeWebRequest req) {
		String realPath = getRealPath(req);

		File folder = new File(realPath, UPLOAD_BASE);
		if (!folder.exists()) {
			folder.mkdirs();
		}
		return folder;
	}

	/**
	 * @param req
	 * @return
	 */
    private static synchronized String getRealPath(NativeWebRequest req) {
		if (realPath != null) {
			return realPath;
		}

		try {
			Object request = req.getNativeRequest();
			Method method = request.getClass().getMethod("getServletContext");
			Object servletContext = method.invoke(request);

			Method getRealPath = servletContext.getClass().getMethod(
					"getRealPath", String.class);
			realPath = (String) getRealPath.invoke(servletContext, "/");
			return realPath;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 
	 * @param file
	 * @return
	 */
	public static String getRelativeUri(File file) {
		return getRelativeUri(realPath, file);
	}

	static String getRelativeUri(String basePath, File file) {
		String absolutePath = file.getAbsolutePath();
		return absolutePath.replace(basePath, "");
	}

	/**
	 * 将临时文件保存起来, 这里保存到: baseFolder / refType / refId 目录下
	 * 
	 * @param files
	 *            文件列表
	 * @param baseFolder
	 *            根文件夹, 所有上传的文件都保存到这里
	 * @param refType
	 *            上传文件所属的实体类型的名称, 根文件夹下的子文件夹
	 * @param refId
	 *            上传文件所属的实体ID
	 */
	public static void save(List<UploadedFile> files, File baseFolder,
			String refType, int refId) {
		if (files == null || files.size() == 0) {
			return;
		}

		File folder = getFolder(baseFolder, refType, refId + "");

		for (UploadedFile file : files) {
			File tmpFile = UploadTmpFileUtil.getTmpFile(file.getUri());
			File targetFile = new File(folder, tmpFile.getName());
			move(tmpFile, targetFile);

			file.setRefType(refType);
			file.setRefId(refId);
			file.setUri(UploadFileUtil.getRelativeUri(targetFile));
		}
	}

    /**
     * 移动文件
     * 
     * @param srcFile
     * @param targetFile
     */
    private static void move(File srcFile, File targetFile) {
        try {
            FileCopyUtils.copy(srcFile, targetFile);
            srcFile.delete();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

	/**
	 * 删除实体的所有文件, 并删除其目录
	 * 
	 * @param baseFolder
	 *            根文件夹, 所有上传的文件都保存到这里
	 * @param refType
	 *            实体类型的名称
	 * @param refId
	 *            实体ID
	 */
	public static void delete(File baseFolder, String refType, int refId) {
		File folder = getFolder(baseFolder, refType, refId + "");

        FileSystemUtils.deleteRecursively(folder);

		String folderName = baseFolder.getName() + "/" + refType + "/" + refId;
		log.debug("delete folder : " + folderName);
	}

	/**
	 * 删除指定的文件
	 * 
	 * @param req
	 *            HTTP 请求
	 * @param uris
	 *            文件路径
	 */
	public static void delete(NativeWebRequest req, String... uris) {
		String realPath = getRealPath(req);
		for (String uri : uris) {
			File file = new File(realPath, uri);
			file.delete();
			log.debug("delete file : " + uri);
		}
	}

	/**
	 * 删除指定的文件
	 * 
	 * @param req
	 *            HTTP 请求
	 * @param files
	 *            要删除的文件列表
	 */
	public static void delete(NativeWebRequest req, List<UploadedFile> files) {
		if (files == null || files.size() == 0) {
			return;
		}

		String realPath = getRealPath(req);
		for (UploadedFile file : files) {
			File f = new File(realPath, file.getUri());
			f.delete();
			log.debug("delete file : " + file.getUri());
		}
	}

    /**
     * @param req
     * @param uri
     * @return
     */
    public static File getFile(NativeWebRequest req, String uri) {
        String realPath = getRealPath(req);
        File file = new File(realPath, uri);
        return file;
    }
}
